﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;

namespace ParallelRuntimeLibrary.Internal
{
    /// <summary>
    /// This class hold the Native method (Windows 32 APIs).
    /// </summary>
    internal static class NativeMethod
    {
        [DllImport("kernel32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
        internal static extern int GetTickCount();

        [DllImport("kernel32.dll")]
        internal static extern uint SetThreadIdealProcessor(IntPtr handle, uint dwIdealProcessor);
        
        [DllImport("kernel32.dll")]
        internal static extern IntPtr GetCurrentProcess();
        
        [DllImport("kernel32.dll")]
        internal static extern IntPtr GetCurrentThread();
        
        [return: MarshalAs(UnmanagedType.Bool)]
        [DllImport("kernel32.dll")]
        internal static extern bool GetProcessAffinityMask(IntPtr hProcess, out UIntPtr lpProcessAffinityMask, out UIntPtr lpSystemAffinityMask);

        [DllImport("kernel32.dll")]
        internal static extern void GetSystemInfo(ref SYSTEM_INFO lpSystemInfo);
        
        [DllImport("kernel32.dll")]
        internal static extern int SwitchToThread();

        [DllImport("kernel32.dll")]
        internal static extern int SuspendThread(IntPtr hThread);

        [StructLayout(LayoutKind.Sequential)]
        internal struct SYSTEM_INFO
        {
            internal int dwOemId;
            internal int dwPageSize;
            internal IntPtr lpMinimumApplicationAddress;
            internal IntPtr lpMaximumApplicationAddress;
            internal IntPtr dwActiveProcessorMask;
            internal int dwNumberOfProcessors;
            internal int dwProcessorType;
            internal int dwAllocationGranularity;
            internal short wProcessorLevel;
            internal short wProcessorRevision;
        }

        internal static int GetProcessorCount()
        {
            UIntPtr ptr;
            UIntPtr ptr2;
            GetProcessAffinityMask(GetCurrentProcess(), out ptr, out ptr2);

            SYSTEM_INFO lpSystemInfo = new SYSTEM_INFO();

            GetSystemInfo(ref lpSystemInfo);
            ulong num = (ulong)(((long)(-1L)) >> (0x40 - lpSystemInfo.dwNumberOfProcessors));
            ulong num2 = num & ptr.ToUInt64();
            int num3 = 0;
            while (num2 > 0L)
            {
                num3++;
                num2 &= num2 - ((ulong)1L);
            }
            return num3;
        }
    }
}
